package com.giibpt.model;


import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.ImprovedNamingStrategy;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;

import com.giibpt.Util;
import com.giibpt.model.entities.Area;
import com.giibpt.model.entities.Evento;
import com.giibpt.model.entities.Flujo;
import com.giibpt.model.entities.SubArea;
import com.giibpt.model.entities.TipoEvento;
import com.giibpt.model.entities.Visitante;
import com.giibpt.rifidi.EtiquetaActiva;

public class HibernateUtil {

    private static final SessionFactory sessionFactory ;
    private static final Configuration configuration ;

    public static Session getSession()    {
        return sessionFactory.getCurrentSession();
        
    }
	
    public static SessionFactory getSessionFactory() {    	
		return sessionFactory;
	}

	public static Configuration getConfiguration() {
		return configuration;
	}

    static {
        try{
        	configuration 	= new Configuration();
        	configuration.setNamingStrategy(ImprovedNamingStrategy.INSTANCE);
        	configuration.configure("/hibernate.cfg.xml");
        	
            sessionFactory 	= configuration.buildSessionFactory();
        }
        catch(Throwable ex){
            ex.printStackTrace();
            //System.err.println("It did not create the session factory." + ex);
            throw new ExceptionInInitializerError(ex);
        }
    }
    
    public static void save(Object object){
    	Session session = getSessionFactory().openSession();
    	session.beginTransaction();
    	session.save(object);
    	session.getTransaction().commit();
    	session.close();
    }

    public static Object get(Class<?>c, Serializable id){
    	Session session = getSessionFactory().openSession();
    	session.beginTransaction();
    	Object obj = session.get(c, id);
    	session.getTransaction().commit();
    	session.close();
    	return obj;
    }
    
    public static void update(Object object){
    	Session session = getSessionFactory().openSession();
    	session.beginTransaction();
    	/*Serializable id = session.getIdentifier(object);
    	
    	Object obj = session.get(object.getClass(), id);
    	session.evict(obj);
    	*/session.update(object);
       	session.getTransaction().commit();
    	session.close();
    }
    
    public static void delete(Object object){
    	Session session = getSessionFactory().openSession();
    	session.beginTransaction();
    	/*Serializable id = session.getIdentifier(object);
    	Object obj = session.get(object.getClass(), id);
    	*/
    	session.delete(object);
       	session.getTransaction().commit();
    	session.close();
    }
    
    @SuppressWarnings("unchecked")
	public static List<Object> list(Class<?> c){
    	List<Object> list;
    	Session session = getSessionFactory().openSession();
    	session.beginTransaction();
    	list = session.createCriteria(c).list();
    	session.close();
    	return list;
    }
    
    @SuppressWarnings("unchecked")
	public static List<SubArea> getSubAreas(Area area){
    	
    	List<SubArea> list = new ArrayList<SubArea>();
    	
    	Session session = getSessionFactory().openSession();
    	session.beginTransaction();
    	list = session.createCriteria(SubArea.class)
    				.add(Restrictions.eq("area", area))  
    				.list();
    	session.close();
    	return list;
    }
    
    
    @SuppressWarnings("unchecked")
	public static List<Object> getVisitantes(String idVisitante){
    	
    	List<Object> list = new ArrayList<Object>();
    	
    	Session session = getSessionFactory().openSession();
    	session.beginTransaction();
    	Criteria  criteria = session.createCriteria(Visitante.class);
    	
    	if(!Util.null2Cero(idVisitante).equals("0")){
    		criteria.add(Restrictions.eq("idVisitante", new Long(idVisitante)));  
    	}
    	list = criteria.list();
    	session.close();
    	return list;
    }
    
    
    public static List<Object> getEventos(String visitanteId, Date date, Area area , SubArea subarea, TipoEvento ... tipoEventos ){
    	List<Object> list;
    	Session session = getSessionFactory().openSession();
    	session.beginTransaction();
    	Criteria criteria = session.createCriteria(Evento.class);
    	
    	if(!Util.null2Cero(visitanteId).equals("0")){
    		criteria.createAlias("etiqueta", "Etiqueta");
        	criteria.createAlias("Etiqueta.visitante", "Visitante");
        	criteria.add(Restrictions.eq("Visitante.idVisitante", new Long(visitanteId)));
    	}
    	
    	if(date != null){
    		criteria.add(Restrictions.eq("fecha", date)); 
    	}
    	if(subarea != null){
    		criteria.createAlias("lector", "Lector");
    		criteria.add(Restrictions.eq("Lector.subArea", subarea)); 
    		
    	}else if(area != null){
    		criteria.createAlias("lector", "Lector");
        	criteria.createAlias("Lector.subArea", "SubArea");
        	
    		criteria.add(Restrictions.eq("SubArea.area", area)); 
    	}
    	if(tipoEventos != null && tipoEventos.length > 0){
        	criteria.add(Restrictions.in("tipoEvento", tipoEventos)); 
    	}
    	
    	
    	
    	criteria.addOrder(Order.desc("fecha"));
    	
    	list = criteria.list();
    	session.close();
    	return list;
    }
    
    
    
    public static boolean existeFlujo(EtiquetaActiva etiquetaActiva){
    	
    	Session session = getSessionFactory().openSession();
    	session.beginTransaction();
    	Criteria criteria = session.createCriteria(Flujo.class);
    	
    	if(etiquetaActiva.getLectorAnterior() == null){
    		criteria.add(Restrictions.isNull("lectorAnterior"));
    	}else{
    		criteria.add(Restrictions.eq("lectorAnterior", etiquetaActiva.getLectorAnterior()));
    	}
    	criteria.add(Restrictions.eq("lectorSiguiente", etiquetaActiva.getLector()));
    	
    	Flujo flujo = (Flujo) criteria.uniqueResult();
    	session.close();
    	
    	return flujo != null;
    }


//    public static Object listEventos(Long idEvento, Area area, ){
//    	
//    	Session session = getSessionFactory().openSession();
//    	session.beginTransaction();
//    	Object obj = session.get(c, id);
//    	session.getTransaction().commit();
//    	session.close();
//    	return obj;
//    }
}
